import React, { ReactNode, useMemo, useRef, useState } from 'react';
import { style2StyleString, elementOfPageRange } from '../../utils';
import './index.scss';

interface DragContainerProps {
  isShow: boolean;
  children: string | ReactNode;
  position?: 'center' | 'topCenter' | 'bottomCenter';
  style?: object;
  className?: string;
  copyStyle?: object;
}

interface PosType {
  left: number | undefined;
  top: number | undefined;
}

const preCls = 'f_drag_container';
let copyDragContainerRef: HTMLDivElement, distanceX: number, distanceY: number;

const DragContainer: React.FC<DragContainerProps> = (props: DragContainerProps) => {
  const { isShow = false, children = null, position = null, style = {}, className = '', copyStyle = {} } = props;
  const dragContainerRef = useRef<HTMLDivElement>(null);
  const [containerPos, setContainerPos] = useState<PosType>({ left: undefined, top: undefined });

  const dragContainerStyle = useMemo(() => {
    const { left, top } = containerPos;
    return {
      ...style,
      left: left !== undefined ? `${left}px` : '',
      top: top !== undefined ? `${top}px` : ''
    };
  }, [containerPos]);

  // 初始位置，拖拽后移除
  const getPosition = useMemo(
    () =>
      (position && !(containerPos.left !== undefined && containerPos.top !== undefined) ? `${preCls}_${position}` : ''),
    [position, containerPos]
  );

  const handleDragMouseDown = (e: any) => {
    const { clientX, clientY } = e;
    const rectPos = dragContainerRef.current && dragContainerRef.current.getBoundingClientRect();
    if (rectPos) {
      const { left, top, width, height } = rectPos;
      distanceX = clientX - left;
      distanceY = clientY - top;
      copyDragContainerRef = document.createElement('div');
      const style = {
        ...copyStyle,
        position: 'fixed',
        left: `${left}px`,
        top: `${top}px`,
        width: `${width}px`,
        height: `${height}px`,
        border: '1px dashed #ccc'
      };

      copyDragContainerRef.setAttribute('style', style2StyleString(style));
      document.documentElement.style.userSelect = 'none';
      document.documentElement.appendChild(copyDragContainerRef);
    }
    document.addEventListener('mousemove', handleDragMouseMove);
    document.addEventListener('mouseup', handleDragMouseUp);
  };

  const handleDragMouseMove = (e: any) => {
    const { clientX, clientY } = e;
    if (distanceX && distanceY) {
      const posX = clientX - distanceX;
      const posY = clientY - distanceY;

      const { x, y } = elementOfPageRange(posX, posY, copyDragContainerRef);
      copyDragContainerRef.style.left = `${x}px`;
      copyDragContainerRef.style.top = `${y}px`;
    }
  };

  const handleDragMouseUp = (e: any) => {
    document.removeEventListener('mousedown', handleDragMouseDown);
    document.removeEventListener('mousemove', handleDragMouseMove);
    document.removeEventListener('mouseup', handleDragMouseUp);

    if (copyDragContainerRef) {
      const { left: _left, top: _top } = copyDragContainerRef.getBoundingClientRect();
      setContainerPos({ left: _left, top: _top });
      document.documentElement.removeChild(copyDragContainerRef);
    }

    document.documentElement.style.userSelect = 'initial';
  };

  return isShow ? (
    <div
      className={`${preCls} ${getPosition} ${className}`}
      style={dragContainerStyle}
      onMouseDown={handleDragMouseDown}
      ref={dragContainerRef}>
      {children}
    </div>
  ) : null;
};

export default DragContainer;
